<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>FoX_sax</title>
  <link rel="stylesheet" type="text/css" href="DoX.css"/>
</head>
<body>
  <div class="DoX">
<h1>SAX</h1>

<p>SAX stands for Simple API for XML, and was originally a Java API for reading XML. (Full details at <a href="http://saxproject.org">http://saxproject.org</a>). SAX implementations exist for most common modern computer languages.</p>

<p>FoX includes a SAX implementation, which translates most of the Java API into Fortran, and makes it accessible to Fortran programs, enabling them to read in XML documents in a fashion as close and familiar as possible to other languages.</p>

<p>SAX is a stream-based, event callback API. Conceptually, running a SAX parser over a document results in the parser generating events as it encounters different XML components, and sends the events to the main program, which can read them and take suitable action.</p>

<h3>Events</h3>

<p>Events are generated when the parser encounters, for example, an element opening tag, or some text, and most events carry some data with them - the name of the tag, or the contents of the text.</p>

<p>The full list of events is quite extensive, and may be seen below. For most purposes, though, it is unlikely that most users will need more than the 5 most common events, documented here.</p>

<ul>
<li><code>startDocument</code> - generated when the parser starts reading the document. No accompanying data.</li>
<li><code>endDocument</code> - generated when the parser reaches the end of the document. No accompanying data.</li>
<li><code>startElement</code> - generated by an element opening tag. Accompanied by tag name, namespace information, and a list of attributes</li>
<li><code>endElement</code> - generated by an element closing tag. Accompanied by tag name, and namespace information.</li>
<li><code>characters</code> - generated by text between tags. Accompanied by contents of text.</li>
</ul>

<p>Given these events and accompanying information, a program can extract data from an XML document.</p>

<h3>Invoking the parser.</h3>

<p>Any program using the FoX SAX parser must a) use the FoX module, and b) declare a derived type variable to hold the parser, like so:</p>

<pre><code>   use FoX_sax
   type(xml_t) :: xp
</code></pre>

<p>The FoX SAX parser then works by requiring the programmer to write a module containing subroutines to receive any of the events they are interested in, and passing these subroutines to the parser.</p>

<p>Firstly, the parser must be initialized, by passing it XML data. This can be done either by giving a filename, which the parser will manipulate, or by passing a string containing an XML document. Thus:</p>

<pre><code>  call open_xml_file(xp, "input.xml", iostat)
</code></pre>

<p>The <code>iostat</code> variable will report back any errors in opening the file.</p>

<p>Alternatively, </p>

<pre><code>  call open_xml_string(xp, XMLstring)
</code></pre>

<p>where <code>XMLstring</code> is a character variable.</p>

<p>To now run the parser over the file, you simply do:</p>

<pre><code> call parse(xp, list_of_event_handlers)
</code></pre>

<p>And once you're finished, you can close the file, and clean up the parser, with:</p>

<pre><code> call close_xml_t(xp)
</code></pre>

<h4>Options to parser</h4>

<p>It is unlikely that most users will need to operate any of these options, but the following are available for use; all are optional boolean arguments to <code>parse</code>.</p>

<ul>
<li><p><code>namespaces</code> <br />
Does namespace processing occur? Default is <code>.true.</code>, and if on, then any non-namespace-well-formed documents will be rejected, and namespace URI resolution will be performed according to the version of XML in question. If off, then documents will be processed without regard for namespace well-formedness, and no namespace URI resolution will be performed.</p></li>
<li><p><code>namespace_prefixes</code>
Are <code>xmlns</code> attributes reported through the SAX parser? Default is <code>.false.</code>; all such attributes are removed by the parser, and transparent namespace URI resolution is performed. If on, then such attributes will be reported, and treated according to the value of <code>xmlns-uris</code> below. (If <code>namespaces</code> is false, this flag has no effect)</p></li>
<li><p><code>validate</code>
Should validation be performed? Default is <code>.false.</code>, no validation checks are made, and the influence of the DTD on the XML Infoset is ignored. (Ill-formed DTD's will still cause fatal errors, of course.) If <code>.true.</code>, then validation will be performed, and the Infoset modified accordingly.</p></li>
<li><p><code>xmlns_uris</code>
Should <code>xmlns</code> attributes have a namespace of <code>http://www.w3.org/2000/xmlns/</code>? Default is <code>.false.</code>. If such attributes are reported, they have no namespace. If <code>.true.</code> then they are supplied with the appropriate namespace. (if <code>namespaces</code> or <code>namespace-prefixes</code> are <code>.false.</code>, then this flag has no effect.)</p></li>
</ul>

<h3>Receiving events</h3>

<p>To receive events, you must construct a module containing event handling subroutines. These are subroutines of a prescribed form - the input &amp; output is predetermined by the requirements of the SAX interface, but the body of the subroutine is up to you.</p>

<p>The required forms are shown in the API documentation below, but here are some simple examples.</p>

<p>To receive notification of character events, you must write a subroutine which takes as input one string, which will contain the characters received. So:</p>

<pre><code>module event_handling
  use FoX_sax
contains

  subroutine characters_handler(chars)
    character(len=*), intent(in) :: chars

    print*, chars
  end subroutine
end module
</code></pre>

<p>That does very little - it simply prints out the data it receives. However, since the subroutine is in a module, you can save the data to a module variable, and manipulate it elsewhere; alternatively you can choose to call other subroutines based on the input.</p>

<p>So, a complete program which reads in all the text from an XML document looks like this:</p>

<pre><code>module event_handling
  use FoX_sax
contains

  subroutine characters_handler(chars)
    character(len=*), intent(in) :: chars

    print*, chars
  end subroutine
end module

program XMLreader
  use FoX_sax
  use event_handling
  type(xml_t) :: xp
  call open_xml_file(xp, 'input.xml')
  call parse(xp, characters_handler=characters_handler)
  call close_xml_t(xp)
end program
</code></pre>

<h3>Attribute dictionaries.</h3>

<p>The other likely most common event is the startElement event. Handling this involves writing a subroutine which takes as input three strings (which are the local name, namespace URI, and fully qualified name of the tag) and a dictionary of attributes. </p>

<p>An attribute dictionary is essentially a set of key:value pairs - where the key is the attributes name, and the value is its value. (When considering namespaces, each attribute also has a URI and localName.)</p>

<p>Full details of all the dictionary-manipulation routines are given in <a href="AttributeDictionaries.html">AttributeDictionaries</a>, but here we shall show the most common.</p>

<ul>
<li><p><code>getLength(dictionary)</code> - returns the number of entries in the dictionary (the number of attributes declared)</p></li>
<li><p><code>hasKey(dictionary, qName)</code> (where <code>qName</code> is a string) returns <code>.true.</code> or <code>.false.</code> depending on whether an attribute named <code>qName</code> is present.</p></li>
<li><p><code>hasKey(dictionary, URI, localname)</code> (where <code>URI</code> and <code>localname</code> are strings) returns <code>.true.</code> or <code>.false.</code> depending on whether an attribute with the appropriate <code>URI</code> and <code>localname</code> is present.</p></li>
<li><p><code>getQName(dictionary, i)</code> (where <code>i</code> is an integer) returns a string containing the key of the <code>i</code>th dictionary entry (ie, the name of the <code>i</code>th attribute.</p></li>
<li><p><code>getValue(dictionary, i)</code> (where <code>i</code> is an integer) returns a string containing the value of the <code>i</code>th dictionary entry (ie the value of the <code>i</code>th attribute.</p></li>
<li><p><code>getValue(dictionary, URI, localname)</code> (where <code>URI</code> and <code>localname</code> are strings) returns a string containing the value of the attribute with the appropriate <code>URI</code> and <code>localname</code> (if it is present)</p></li>
</ul>

<p>So, a simple subroutine to receive a startElement event would look like:</p>

<pre><code>module event_handling

contains

 subroutine startElement_handler(URI, localname, name,attributes)
   character(len=*), intent(in)   :: URI  
   character(len=*), intent(in)   :: localname
   character(len=*), intent(in)   :: name 
   type(dictionary_t), intent(in) :: attributes

   integer :: i

   print*, name

   do i = 1, getLength(attributes)
      print*, getQName(attributes, i), '=', getValue(attributes, i)
   enddo

  end subroutine startElement_handler
end module

program XMLreader
 use FoX_sax
 use event_handling
 type(xml_t) :: xp
 call open_xml_file(xp, 'input.xml')
 call parse(xp, startElement_handler=startElement_handler)
 call close_xml_t(xp)
end program
</code></pre>

<p>Again, this does nothing but print out the name of the element, and the names and values of all of its attributes. However, by using module variables, or calling other subroutines, the data could be manipulated further.</p>

<h3>Error handling</h3>

<p>The SAX parser detects all XML well-formedness errors (and optionally validation errors). By default, when it encounters an error, it will simply halt the program with a suitable error message. However, it is possible to pass in an error handling subroutine if some other behaviour is desired - for example it may be nice to report the error to the user, finish parsing, and carry on with some other task.</p>

<p>In any case, once an error is encountered, the parser will finish. There is no way to continue reading past an error. (This means that all errors are treated as fatal errors, in the terminology of the XML standard).</p>

<p>An error handling subroutine works in the same way as any other event handler, with the event data being an error message. Thus, you could write:</p>

<pre><code>subroutine fatalError_handler(msg)
  character(len=*), intent(in) :: msg

  print*, "The SAX parser encountered an error:"
  print*, msg
  print*, "Never mind, carrying on with the rest of the calcaulation."
end subroutine
</code></pre>

<h3>Stopping the parser.</h3>

<p>The parser can be stopped at any time. Simply do (from within one of the callback functions).</p>

<pre><code>call stop_parser(xp)
</code></pre>

<p>(where <code>xp</code> is the XML parser object). The current callback function will be completed, then the parser will be stopped, and control will return to the main program, the parser having finished.</p>

<hr />

<h2>Full API</h2>

<h3>Derived types</h3>

<p>There is one derived type, <code>xml_t</code>. This is entirely opaque, and is used as a handle for the parser.</p>

<h3>Subroutines</h3>

<p>There are four subroutines:</p>

<ul>
<li><code>open_xml_file <br />
type(xml_t), intent(inout) :: xp <br />
character(len=*), intent(in) :: string <br />
integer, intent(out), optional :: iostat</code></li>
</ul>

<p>This opens a file. <code>xp</code> is initialized, and prepared for parsing. <code>string</code> must contain the name of the file to be opened. <code>iostat</code> reports on the success of opening the file. A value of <code>0</code> indicates success.</p>

<ul>
<li><p><code>open_xml_string <br />
type(xml_t), intent(inout) :: xpi <br />
character(len=*), intent(in) :: string</code></p>

<p>This prepares to parse a string containing XML data. <code>xp</code> is initialized. <code>string</code> must contain the XML data.</p></li>
<li><p><code>close_xml_t <br />
type(xml_t), intent(inout) :: xp</code></p></li>
</ul>

<p>This closes down the parser (and closes the file, if input was coming from a file.) <code>xp</code> is left uninitialized, ready to be used again if necessary.</p>

<ul>
<li><p><code>parse <br />
type(xml_t), intent(inout) :: xp <br />
external :: list of event handlers <br />
logical, optional, intent(in) :: validate</code></p>

<p>This tells <code>xp</code> to start parsing its document. </p></li>
</ul>

<p>(<em>Advanced: See above for the list of options that the <code>parse</code> subroutine may take.</em>)</p>

<p>The full list of event handlers is in the next section. To use them, the interface must be placed in a module, and the body of the subroutine filled in as desired; then it should be specified as an argument to <code>parse</code> as: <br />
  <code>name_of_event_handler = name_of_user_written_subroutine</code> <br />
Thus a typical call to <code>parse</code> might look something like:</p>

<pre><code>  call parse(xp, startElement_handler = mystartelement, endElement_handler = myendelement, characters_handler = mychars)
</code></pre>

<p>where <code>mystartelement</code>, <code>myendelement</code>, and <code>mychars</code> are all  subroutines written by you according to the interfaces listed below.</p>

<hr />

<h2>Callbacks.</h2>

<p>All of the callbacks specified by SAX 2 are implemented. Documentation of the SAX 2 interfaces is available in the JavaDoc at <a href="http://sax_project.org">http://saxproject.org</a>, but as the interfaces needed adjustment for Fortran, they are listed here.</p>

<p>For documentation on the meaning of the callbacks and of their arguments, please refer to the Java SAX documentation.</p>

<ul>
<li><code>characters_handler <br />
  subroutine characters_handler(chunk) <br />
    character(len=*), intent(in) :: chunk <br />
  end subroutine characters_handler</code></li>
</ul>

<p>Triggered when some character data is read from between tags. </p>

<p>NB Note that <em>all</em> character data is reported, including whitespace. Thus you will probably get a lot of empty <code>characters</code> events in a typical XML document.</p>

<p>NB Note also that it is not required that a single chunk of character data all come as one event - it may come as multiple consecutive events. You should concatenate the results of subsequent character events before processing.</p>

<ul>
<li><code>endDocument_handler <br />
  subroutine endDocument_handler() <br />
  end subroutine endDocument_handler</code></li>
</ul>

<p>Triggered when the parser reaches the end of the document.</p>

<ul>
<li><code>endElement_handler <br />
  subroutine endElement_handler(namespaceURI, localName, name) <br />
    character(len=*), intent(in)     :: namespaceURI <br />
    character(len=*), intent(in)     :: localName <br />
    character(len=*), intent(in)     :: name <br />
  end subroutine endElement_handler</code></li>
</ul>

<p>Triggered by a closing tag.</p>

<ul>
<li><code>endPrefixMapping_handler <br />
  subroutine endPrefixMapping_handler(prefix) <br />
    character(len=*), intent(in) :: prefix <br />
  end subroutine endPrefixMapping_handler</code></li>
</ul>

<p>Triggered when a namespace prefix mapping goes out of scope.</p>

<ul>
<li><code>ignorableWhitespace <br />
  subroutine ignorableWhitespace_handler(chars) <br />
    character(len=*), intent(in) :: chars <br />
  end subroutine ignorableWhitespace_handler</code></li>
</ul>

<p>Triggered when whitespace is encountered within an element declared as having no PCDATA. (Only active in validating mode.)</p>

<ul>
<li><code>processingInstruction_handler <br />
  subroutine processingInstruction_handler(name, content) <br />
    character(len=*), intent(in)     :: name <br />
    character(len=*), intent(in)     :: content <br />
  end subroutine processingInstruction_handler</code></li>
</ul>

<p>Triggered by a Processing Instruction</p>

<ul>
<li><code>skippedEntity_handler <br />
  subroutine skippedEntity_handler(name) <br />
    character(len=*), intent(in) :: name <br />
  end subroutine skippedEntity_handler</code></li>
</ul>

<p>Triggered when either an external entity, or an undeclared entity, is skipped.</p>

<ul>
<li><code>startDocument_handler <br />
  subroutine startDocument_handler() <br />
  end subroutine startDocument_handler</code></li>
</ul>

<p>Triggered when the parser starts reading the document.</p>

<ul>
<li><code>startElement_handler <br />
  subroutine startElement_handler(namespaceURI, localName, name, attributes) <br />
    character(len=*), intent(in)     :: namespaceUri <br />
    character(len=*), intent(in)     :: localName <br />
    character(len=*), intent(in)     :: name <br />
    type(dictionary_t), intent(in)   :: attributes <br />
  end subroutine startElement_handler</code></li>
</ul>

<p>Triggered when an opening tag is encountered. (see LINK for documentation on handling attribute dictionaries.</p>

<ul>
<li><code>startPrefixMapping_handler <br />
  subroutine startPrefixMapping_handler(namespaceURI, prefix) <br />
    character(len=*), intent(in) :: namespaceURI <br />
    character(len=*), intent(in) :: prefix <br />
  end subroutine startPrefixMapping_handler</code></li>
</ul>

<p>Triggered when a namespace prefix mapping start.</p>

<ul>
<li><code>notationDecl_handler <br />
  subroutine notationDecl_handler(name, publicId, systemId) <br />
    character(len=*), intent(in) :: name <br />
    character(len=*), intent(in) :: publicId <br />
    character(len=*), intent(in) :: systemId <br />
  end subroutine notationDecl_handler</code></li>
</ul>

<p>Triggered when a NOTATION declaration is made in the DTD</p>

<ul>
<li><code>unparsedEntityDecl_handler <br />
  subroutine unparsedEntityDecl_handler(name, publicId, systemId, notation) <br />
    character(len=*), intent(in) :: name <br />
    character(len=*), intent(in) :: publicId <br />
    character(len=*), intent(in) :: systemId <br />
    character(len=*), intent(in) :: notation <br />
  end subroutine unparsedEntityDecl_handler</code></li>
</ul>

<p>Triggered when an unparsed entity is declared</p>

<ul>
<li><code>error_handler <br />
  subroutine error_handler(msg) <br />
    character(len=*), intent(in)     :: msg <br />
  end subroutine error_handler</code></li>
</ul>

<p>Triggered when a <a href="http://www.w3.org/TR/REC-xml/#dt-error">error</a> is encountered in parsing. Parsing will continue after this event.</p>

<ul>
<li><code>fatalError_handler <br />
  subroutine fatalError_handler(msg) <br />
    character(len=*), intent(in)     :: msg <br />
  end subroutine fatalError_handler</code></li>
</ul>

<p>Triggered when a <a href="http://www.w3.org/TR/REC-xml/#dt-fatal">fatal error</a> is encountered in parsing. Parsing will cease after this event.</p>

<ul>
<li><code>warning_handler <br />
  subroutine warning_handler(msg) <br />
    character(len=*), intent(in)     :: msg <br />
  end subroutine warning_handler</code></li>
</ul>

<p>Triggered when a parser warning is generated. Parsing will continue after this event.</p>

<ul>
<li><code>attributeDecl_handler <br />
  subroutine attributeDecl_handler(eName, aName, type, mode, value) <br />
    character(len=*), intent(in) :: eName <br />
    character(len=*), intent(in) :: aName <br />
    character(len=*), intent(in) :: type <br />
    character(len=*), intent(in) :: mode <br />
    character(len=*), intent(in) :: value <br />
  end subroutine attributeDecl_handler</code></li>
</ul>

<p>Triggered when an attribute declaration is encountered in the DTD.</p>

<ul>
<li><code>elementDecl_handler <br />
  subroutine elementDecl_handler(name, model) <br />
    character(len=*), intent(in) :: name <br />
    character(len=*), intent(in) :: model <br />
  end subroutine elementDecl_handler</code></li>
</ul>

<p>Triggered when an element declaration is enountered in the DTD.</p>

<ul>
<li><code>externalEntityDecl_handler <br />
  subroutine externalEntityDecl_handler(name, publicId, systemId) <br />
    character(len=*), intent(in) :: name <br />
    character(len=*), intent(in) :: publicId <br />
    character(len=*), intent(in) :: systemId <br />
  end subroutine externalEntityDecl_handler</code></li>
</ul>

<p>Triggered when a parsed external entity is declared in the DTD.</p>

<ul>
<li><code>internalEntityDecl_handler <br />
  subroutine internalEntityDecl_handler(name, value) <br />
    character(len=*), intent(in) :: name <br />
    character(len=*), intent(in) :: value <br />
  end subroutine internalEntityDecl_handler</code></li>
</ul>

<p>Triggered when an internal entity is declared in the DTD.</p>

<ul>
<li><code>comment_handler <br />
  subroutine comment_handler(comment) <br />
    character(len=*), intent(in) :: comment <br />
  end subroutine comment_handler</code></li>
</ul>

<p>Triggered when a comment is encountered.</p>

<ul>
<li><code>endCdata_handler <br />
  subroutine endCdata_handler() <br />
  end subroutine endCdata_handler</code></li>
</ul>

<p>Triggered by the end of a CData section.</p>

<ul>
<li><code>endDTD_handler <br />
  subroutine endDTD_handler() <br />
  end subroutine endDTD_handler</code></li>
</ul>

<p>Triggered by the end of a DTD.</p>

<ul>
<li><code>endEntity_handler <br />
  subroutine endEntity_handler(name) <br />
    character(len=*), intent(in) :: name <br />
  end subroutine endEntity_handler</code></li>
</ul>

<p>Triggered at the end of entity expansion.</p>

<ul>
<li><code>startCdata_handler <br />
  subroutine startCdata_handler() <br />
  end subroutine startCdata_handler</code></li>
</ul>

<p>Triggered by the start of a CData section.</p>

<ul>
<li><code>startDTD_handler <br />
  subroutine startDTD_handler(name, publicId, systemId) <br />
    character(len=*), intent(in) :: name <br />
    character(len=*), intent(in) :: publicId <br />
    character(len=*), intent(in) :: systemId <br />
  end subroutine startDTD_handler</code></li>
</ul>

<p>Triggered by the start of a DTD section.</p>

<ul>
<li><code>startEntity_handler <br />
  subroutine startEntity_handler(name) <br />
    character(len=*), intent(in) :: name <br />
  end subroutine startEntity_handler</code></li>
</ul>

<p>Triggered by the start of entity expansion.</p>

<hr />

<h3>Exceptions.</h3>

<p>The FoX SAX implementation implements all of XML 1.0 and 1.1; all of XML Namespaces 1.0 and 1.1; xml:id and xml:base.</p>

<p>Although FoX tries very hard to  work to the letter of the XML and SAX standards, it falls short in a few areas.</p>

<ul>
<li><p>FoX will only process documents consisting of nothing but US-ASCII data. It will accept documents labelled with any single byte character set which is identical to US-ASCII in its lower 7 bits (for example, any of the ISO-8859 charsets, or UTF-8) but an error will be generated as soon as any character outside US-ASCII is encountered. (This includes non-ASCII characters present only be character entity reference)</p></li>
<li><p>As a corollary, UTF-16 documents of any endianness will also be rejected.</p></li>
</ul>

<p>(It is impossible to implement IO of non-ASCII documents in a portable fashion using standard Fortran 95, and it is impossible to handle non-ASCII data internally using standard Fortran strings. A fully unicode-capable FoX version is under development, but requires Fortran 2003. Please enquire for further details if you're interested.)</p>

<ul>
<li>FoX has no network capabilities. Therefore, when external entities are referenced, any entities not available on the local filesystem will not be accessed (specifically, any entities whose URI reference includes a scheme component, where that scheme is not <code>file</code>, will be skipped)</li>
</ul>

<p>Beyond this, any aspects of the listed XML standards to which FoX fails to do justice to are bugs.</p>

<hr />

<h3>What of Java SAX 2 is not included in FoX?</h3>

<p>The difference betweek Java &amp; Fortran means that none of the SAX APIs can be copied directly. However, FoX offers data types, subroutines, and interfaces covering most of the facilities offered by SAX. Where it does not, this is mentioned here.</p>

<p>org.sax.xml:</p>

<ul>
<li>Querying/setting of feature flags/property values for the XML parser. The effect of a subset of these may be accessed by options to the <code>parse</code> subroutine.</li>
<li>XML filters - Java SAX makes it possible to write filters to intercept the
flow of events. FoX does not support this.  </li>
<li>Entity resolution - SAX 2 exports an interface to the application for entity resolution, but FoX does not - all entities are resolved within the parser.</li>
<li>Locator - SAX 2 offers an interface to export information regarding object locations within the document, FoX does not.  </li>
<li>XMLReader - FoX only offers the parse() method - no other methods really make sense in Fortran.  </li>
<li>AttributeList/DocumentHandler/Parser - FoX only offers namespace aware attributes, not the pre-namespace SAX-1 versions.  </li>
</ul>

<p>org.sax.xml.ext:</p>

<ul>
<li>EntityResolver2 - not implemented  </li>
<li>Locator2 - not implemented  </li>
</ul>

<p>org.sax.xml.helpers:</p>

<ul>
<li>None of these helper methods are implemented.</li>
</ul>
</div>
</body>
</html>
